# -*- coding: utf-8 -*-
import _thread
import cv2
import numpy as np
import os
from ctypes import *
from tkinter import *
from PIL import Image,ImageTk
from tkinter import scrolledtext
from tkinter import messagebox
from tkinter  import ttk 
from tkinter import END
import inspect
import threading
import sys
import inspect
import serial.tools.list_ports
#my py moudel
import sendAndRecevice as SR
#load path
import enviroment
import solution

################全局变量####################
camera_index =1  
camera_status = 0 
scr=1
camra1Opened=0 #
camra2Opened=0 #
camra3Opened=0 #
camra4Opened=0 #
camraNum=1
real_port_list= []

###############函数###################

#文字框插入信息
def insert(text):

    global scr
    scr.insert("insert",str(text))
    scr.see(END)
            
#文字框清空
def clear():
    scr.delete(0.0, END)
    insert("****欢迎使用魔方机器人*****\n")

      

def main():

###############主函数#####################

    def placeCubeThread():
        solution.place();

    #[0,1,2]
    def initSelectBox(array):
        com1['values'] = tuple(array)
        com2['values'] = tuple(array)
        com3['values'] = tuple(array)
        com4['values'] = tuple(array)
        
    def searchCamra():
        cameraPortList=[]
        for i in range(10):
            camera = cv2.VideoCapture(int(i))
            if(camera.isOpened()):
                camera.release()
                cameraPortList.append(i);
                print("搜索到摄像头索引："+str(i))
        initSelectBox(cameraPortList);

        
    #放置魔方
    def placeCube():
        placeThread = threading.Thread(target=placeCubeThread)   
        placeThread.start();
        
    #解算魔方
    def runSolveCube():
        global camera1,camera2,camera3,camera4
        global camraNum
        camraNum = int(comCamera.get())
        try:
            if camraNum==1 and camera1.isOpened():
                insert("1个摄像头\n");
                boolValue,res=solution.oneCameraSolutionWithBlack(camera1);
                insert(res+"\n");
            elif camraNum==4 and camera1.isOpened() and camera2.isOpened() and camera3.isOpened() and camera4.isOpened():
                insert("4个摄像头\n");
                boolValue,res=solution.fourCameraSolutionWithBlack(camera1,camera2,camera3,camera4);
                insert(res+"\n");
            else :
                insert("摄像头未打开\n");
        except BaseException as err:
            print("有异常:",err);
            return;
            
    #选择摄像头个数
    def selectCarma(num):
        global camraNum
        camraNum = num
    #运行
    def run():
        t3 = threading.Thread(target=runSolveCube)   
        t3.start();
        
    #打开摄像头
    def openCamera(port):
        insert("准备打开摄像头\n")
        camera = cv2.VideoCapture(int(port))
        for i in range(5):
            camera.set(cv2.CAP_PROP_EXPOSURE, -10);
        camera.set(3,400)
        camera.set(4,400)
        if(camera.isOpened()):
            insert("摄像头打开成功！\n")
            return True,camera;
        else:
            insert("摄像头打开失败\n")
            return False,camera;
        
    #打开摄像头线程
    def openTopCamera(camera_port):
        global camera1
        res,camera1=openCamera(camera_port);
        if res:
            showImgTop();
    
    def openBottomCamera(camera_port):
        global camera2
        res,camera2=openCamera(camera_port);
        if res:
            showImgBottom();
      
    def openLeftCamera(camera_port):
        global camera3
        res,camera3=openCamera(camera_port);
        if res:
            showImgLeft();
            
    def openRightCamera(camera_port):
        global camera4
        res,camera4=openCamera(camera_port);
        if res:
            showImgRight();
            

    def open_camera(i,camera_port):
        insert(i)
        if i==1:
            threading.Thread(target=openTopCamera,args=(camera_port)).start(); 
        elif i==2:
            threading.Thread(target=openBottomCamera,args=(camera_port)).start();
        elif i==3:
            threading.Thread(target=openLeftCamera,args=(camera_port)).start(); 
        elif i==4:
            threading.Thread(target=openRightCamera,args=(camera_port)).start(); 
 
    #从camera中获取图片并转换成tkinter可以显示的类型      
    def getTkinterImg(camera):
        success,img = camera.read()
        img=cv2.resize(img,(320,240));
        if(success==False):
            insert("无法获取当前图片！")
            return
        cv2image = cv2.cvtColor(img, cv2.COLOR_BGR2RGBA)
        current_image = Image.fromarray(cv2image)
        imgtk = ImageTk.PhotoImage(image=current_image)
        return imgtk;

    #循环显示图片到panel中
    def showImgTop():
        global camera1
        while camera1.isOpened():
           imgtk = getTkinterImg(camera1)
           panel1.imgtk = imgtk
           panel1.config(image=imgtk)

    ##展示摄像头图片
    def showImgBottom():
        global camera2
        while camera2.isOpened():
           imgtk = getTkinterImg(camera2)
           panel2.imgtk = imgtk
           panel2.config(image=imgtk)
    
    
    def showImgLeft():
        global camera3
        while camera3.isOpened():
           imgtk = getTkinterImg(camera3)
           panel3.imgtk = imgtk
           panel3.config(image=imgtk)
     
    def showImgRight():
        global camera4
        while camera4.isOpened():
           imgtk = getTkinterImg(camera4)
           panel4.imgtk = imgtk
           panel4.config(image=imgtk)
 
    #初始化
    def init_env_thread():
        solution.initEnvirment();
        
    #初始化环境
    def init_env():
        initThread = threading.Thread(target=init_env_thread)   
        initThread.start();
    
    def openPawThread():
        solution.openClaw();
    #打开爪子
    def open_paw():
        t1 = threading.Thread(target=openPawThread).start();

    #关闭摄像头
    def close_camera():
        global camera1,camera2,camerq3,camer4
        
        if (camra1Opened):
            camera1.release()
            insert("关闭摄像头1成功！")
            print("关闭摄像头1成功！")
            
        if (camra2Opened):
            camera2.release()
            insert("关闭摄像头2成功！")
            print("关闭摄像头2成功！")
            
        if (camra3Opened):
            camera3.release()
            insert("关闭摄像头3成功！")
            print("关闭摄像头3成功！")
            
        if (camra4Opened):
            camera4.release()
            insert("关闭摄像头4成功！")
            print("关闭摄像头4成功！")            

###################################

    #主界面
    t = Tk()
    #标题
    t.title('魔方机器人')
    t.resizable(0,0) #宽高固定
 
############fun###################

    #关闭窗口
    def close_window():
        if messagebox.askokcancel("提醒","是否确定关闭窗口?"):
            #GPIO.cleanup();
            close_camera()
            t.destroy()
            sys.exit()

    def sendInstructionThread():
        instruction = E1.get()
        if(len(instruction)> 0):
            SR.sendData(str(instruction))
            pass

    def sendInstruction():
        sendInThread = threading.Thread(target=sendInstructionThread)   
        sendInThread.start();
    
    #选择串口号
    def select_serial():
        current_port = str(com5.get())
        SR.open_port(current_port);

    def searchPort():
        global real_port_list
        while True:
            real_port_list = []
            #获取串口列表信息并存放在real_port_list
            port_list = list(serial.tools.list_ports.comports())
            for port in list(port_list):
                real_port_list.append(port[0])
            #设置值
            com5["values"]= real_port_list
     
    #串口列表初始化
    def serialPortInit():
        global real_port_list
        #初始化
        real_port_list = []
        #获取串口列表信息并存放在real_port_list
        port_list = list(serial.tools.list_ports.comports())
        for port in list(port_list):
            real_port_list.append(port[0])
        #设置值
        com5["values"]= real_port_list
        threading.Thread(target=searchPort).start()
            
 
############fun################## 

    #左边容器
    frmLT = Frame(width=730, height=630)
    #右边容器
    frmRT = Frame(width=350, height=630)
    
    frmLT.grid(row=0, column=0)
    frmRT.grid(row=0, column=1)

 
    ##上方组件布局
    com1 = ttk.Combobox(frmLT, width='3',state="readonly")        
    com1.place(x=20,y=15)
    
    left_btn = Button(frmLT,text="打开上",command=lambda:open_camera(1,com1.get()),font=(14))
    left_btn.place(x=64,y=10)
    

    com2 = ttk.Combobox(frmLT, width='3',state="readonly")
    com2.place(x=245,y=15)    
 
    up_btn = Button(frmLT,text="打开下",command=lambda:open_camera(2,com2.get()),font=(14))
    up_btn.place(x=289,y=10)
    

    
    com3 = ttk.Combobox(frmLT, width='3',state="readonly")
    com3.place(x=20,y=60)
    
    right_btn=Button(frmLT,text="打开左",command=lambda:open_camera(3,com3.get()),font=(14))
    right_btn.place(x=64,y=55)
    
    
    com4 = ttk.Combobox(frmLT, width='3',state="readonly")
    com4.place(x=245,y=60)

    
    
    down_btn = Button(frmLT,text="打开右",command=lambda:open_camera(4,com4.get()),font=(14))
    down_btn.place(x=289,y=55)

    searchCamra()
    
    labelCamera = Label(text='摄像头数量:')
    labelCamera.place(x=400,y=15)
    
    #打开摄像头列表
    comCamera = ttk.Combobox(frmLT, width='3',state="readonly")
    comCamera['values'] = [1,4]
    comCamera.current(0)
    comCamera.place(x=470,y=15)

    com5 = ttk.Combobox(frmLT, width='7',state="readonly")
    #com5["values"]= get_port_list()
    com5.place(x=565,y=15)
    
    serial_btn = Button(frmLT,text="打开",command=select_serial,font=(14))
    serial_btn.place(x= 637, y=13)

    #输入命令框

    
    labelCode = Label(text='命令:')
    labelCode.place(x=400,y=56)
    E1 = Entry(t, bd=4,width= 28)
    E1.place(x= 432,y=55)
    send_data_btn = Button(frmLT,text="发送",command=sendInstruction)
    send_data_btn.place(x= 640,y=53)



    #右边文字框

    global scr
    scr = scrolledtext.ScrolledText(frmRT, width=330, height=470,font=(14),state=NORMAL)
    scr.place(x=0,y=0, width=350, height=600)
    insert("****欢迎使用魔方机器人*****\n");



    ##下方组件布局
 
    palce_cube_btn = Button(frmLT,text="放置",command=placeCube,font=(14),padx= 5)
    palce_cube_btn.place(x= 50, y=590)
    

    open_camera_btn = Button(frmLT,text="初始化",command=init_env,font=(14))
    open_camera_btn.place(x= 150, y=590)
    
    open_paw_btn = Button(frmLT,text="打开爪子",command=open_paw,font=(14))
    open_paw_btn.place(x= 230, y=590)

    run_btn = Button(frmLT,text="运行",command=run,font=(38),bg='#5cb85c',bd = 7)
    run_btn.place(x= 350, y=585)


    clear_data_btn = Button(frmLT,text="清除数据",command=clear,font=(14))
    clear_data_btn.place(x= 450, y=590)
    

    #四个摄像头位置
    
    panel1 = Label(t)  # initialize image panel
    panel1.place(x=30,y=90)#
    
    panel2 = Label(t)  # initialize image panel
    panel2.place(x=370,y=90)#
    
    panel3 = Label(t)  # initialize image panel
    panel3.place(x=30,y=340)#
    
    panel4 = Label(t)  # initialize image panel
    panel4.place(x=370,y=340)#
    
    #获取串口列表
    serialPortInit()
    t.protocol("WM_DELETE_WINDOW",close_window)
    t.mainloop()




t1 = threading.Thread(target=main)   
t1.start()


SR.register(insert);

